package com.xjoyt.pay.master.services;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.xjoyt.pay.abstracts.AbstractService;
import com.xjoyt.pay.commons.ObjectUtils;
import com.xjoyt.pay.commons.PayTypeUtils;
import com.xjoyt.pay.dto.ExecuteResult;
import com.xjoyt.pay.dto.PageParam;
import com.xjoyt.pay.dto.PageResult;
import com.xjoyt.pay.master.params.MerchantChannelPageParam;
import com.xjoyt.pay.master.po.MerchantChannel;
import com.xjoyt.pay.master.po.MerchantChannelCashRate;
import com.xjoyt.pay.master.po.MerchantChannelRate;
import com.xjoyt.pay.master.po.MerchantRate;
import com.xjoyt.pay.master.repository.MerchantChannelCashRateRepository;
import com.xjoyt.pay.master.repository.MerchantChannelRateRepository;
import com.xjoyt.pay.master.repository.MerchantChannelRepository;
import com.xjoyt.pay.master.repository.MerchantRateRepository;
import com.xjoyt.pay.master.vo.MerchantChannelMap;
import com.xjoyt.pay.master.vo.MerchantRateMap;
import com.xjoyt.pay.master.vo.RateEntry;
import com.xjoyt.pay.vo.PayType;

@Service
public class MerchantChannelService extends AbstractService {

	@Autowired
	private MerchantChannelRepository repository;

	@Autowired
	private MerchantRateRepository merchantRateRepository;

	@Autowired
	private MerchantChannelRateRepository merchantChannelRateRepository;

	@Autowired
	private MerchantChannelCashRateRepository merchantChannelCashRateRepository;

	@Autowired
	private RestTemplate restTemplate;

	@Autowired
	private MerchantChannelRepository merchantChannelRepository;

	public PageResult<MerchantChannelMap> loadPage(PageParam<MerchantChannelPageParam> param) {
		PageResult<MerchantChannel> page = repository.loadPage(param);
		List<MerchantChannelMap> rows = new ArrayList<>();

		List<String> ids = new ArrayList<>();
		page.forEach(item -> {
			ids.add(String.valueOf(item.id));
			MerchantChannelMap vo = new MerchantChannelMap();
			rows.add(vo);
			ObjectUtils.fieldCopy(item, vo);
		});
		List<MerchantChannelRate> list = CollectionUtils.isEmpty(ids) ? new ArrayList<>()
				: merchantChannelRateRepository.findAllByMerchantChannelIdIn(ids);
		List<MerchantChannelCashRate> cashList = CollectionUtils.isEmpty(ids) ? new ArrayList<>()
				: merchantChannelCashRateRepository.findAllByMerchantChannelIdIn(ids);
		rows.forEach(item -> {
			item.rateList = new ArrayList<>();
			for (PayType type : PayType.values()) {
				RateEntry entry = new RateEntry();
				entry.type = type;
				item.rateList.add(entry);
				entry.name = PayTypeUtils.getName(type);
				for (MerchantChannelRate merchantChannelRate : list) {
					if (merchantChannelRate.money == null || merchantChannelRate.limit == null
							|| merchantChannelRate.minimum == null)
						continue;
					if (type.equals(merchantChannelRate.type)
							&& item.id==merchantChannelRate.merchantChannel.id) {
						entry.rate = merchantChannelRate.rate;
						entry.money = merchantChannelRate.money;
						entry.limit = merchantChannelRate.limit;
						entry.minimum = merchantChannelRate.minimum;
						break;
					}
				}
			}
			for (MerchantChannelCashRate merchantChannelCashRate : cashList) {
				if (merchantChannelCashRate.money == null || merchantChannelCashRate.rate == null
						|| merchantChannelCashRate.limit == null || merchantChannelCashRate.minimum == null)
					continue;
				item.cashMoney = merchantChannelCashRate.money;
				item.cashRate = merchantChannelCashRate.rate;
				item.cashLimit = merchantChannelCashRate.limit;
				item.cashMinimum = merchantChannelCashRate.minimum;
			}
		});

		return new PageResult<>(page.getTotal(), rows);
	}

	public ExecuteResult<?> save(MerchantChannelMap param) {
		if (param.merchant == null || param.channel == null || StringUtils.isBlank(param.merchant.id)
				|| StringUtils.isBlank(param.channel.id)) {
			return ExecuteResult.fail("数据不存在");
		}

		repository.findAllByMerchantIdAndChannelId(param.merchant.id, param.channel.id).forEach(item -> {
			item.enabled = false;
			repository.save(item);
		});

		MerchantChannel merchantChannel = new MerchantChannel();
		ObjectUtils.fieldCopy(param, merchantChannel);
		merchantChannel.id = null;
		merchantChannel.addedDate = new Date();
		merchantChannel = repository.save(merchantChannel);
		for (RateEntry item : param.rateList) {
			if (StringUtils.isBlank(PayTypeUtils.getName(item.type)))
				continue;
			MerchantChannelRate entity = new MerchantChannelRate();
			entity.type = item.type;
			entity.rate = item.rate;
			entity.money = item.money;
			entity.limit = item.limit;
			entity.minimum = item.minimum;
			entity.merchantChannel = merchantChannel;
			merchantChannelRateRepository.save(entity);
		}
		if (String.valueOf(param.cashLimit) != null || String.valueOf(param.cashRate) != null
				|| String.valueOf(param.cashMinimum) != null || String.valueOf(param.cashMoney) != null) {
			MerchantChannelCashRate entity = new MerchantChannelCashRate();
			entity.merchantChannel = merchantChannel;
			entity.rate = param.cashRate;
			entity.limit = param.cashLimit;
			entity.money = param.cashMoney;
			entity.minimum = param.cashMinimum;
			merchantChannelCashRateRepository.save(entity);
		}

		return ExecuteResult.ok();
	}

	public ExecuteResult<?> saveAuto(MerchantChannelMap entity) {
		repository.findAllByMerchantIdAndChannelId(entity.merchant.id, entity.channel.id).forEach(item -> {
			item.enabled = false;
			repository.save(item);
		});
		List<MerchantRate> rateList = merchantRateRepository.findAllByMerchantId(entity.merchant.id);
		if (CollectionUtils.isEmpty(rateList)) {
			return ExecuteResult.fail();
		}

		MerchantRateMap param = new MerchantRateMap();
		ObjectUtils.fieldCopy(entity.merchant, param);
		param.rateList = new ArrayList<>();
		rateList.forEach(i -> {
			RateEntry entry = new RateEntry();
			entry.type = i.type;
			entry.rate = i.rate;
		});
		try {
			MerchantChannelMap merchantChannel = restTemplate.postForObject(entity.channel.registerUrl, param,
					MerchantChannelMap.class);
			if (merchantChannel == null || StringUtils.isBlank(merchantChannel.key)
					|| StringUtils.isBlank(merchantChannel.no)) {
				return ExecuteResult.fail();
			}
			merchantChannelRepository.findAllByMerchantIdAndChannelId(String.valueOf(entity.id), entity.channel.id)
					.forEach(i -> merchantChannelRepository.delete(i));
			MerchantChannel po = new MerchantChannel();
			ObjectUtils.fieldCopy(merchantChannel, po);
			po.rates = new ArrayList<>();
			po.channel = entity.channel;
			po.addedDate = new Date();
			po.merchant = entity.merchant;
			po.enabled = true;
			po = merchantChannelRepository.save(po);
			if (CollectionUtils.isNotEmpty(merchantChannel.rateList))
				for (RateEntry i : merchantChannel.rateList) {
					if (i.rate <= 0 || i.type == null)
						continue;
					MerchantChannelRate r = new MerchantChannelRate();
					r.merchantChannel = po;
					r.rate = i.rate;
					r.type = i.type;
					r.limit = i.limit;
					r.money = i.money;
					r.minimum = i.minimum;
					merchantChannelRateRepository.save(r);
				}
			if (String.valueOf(param.cashLimit) != null || String.valueOf(param.cashRate) != null
					|| String.valueOf(param.cashMinimum) != null || String.valueOf(param.cashMoney) != null) {
				MerchantChannelCashRate cashEntity = new MerchantChannelCashRate();
				cashEntity.merchantChannel = merchantChannel;
				cashEntity.rate = param.cashRate;
				cashEntity.limit = param.cashLimit;
				cashEntity.money = param.cashMoney;
				cashEntity.minimum = param.cashMinimum;
			}

		} catch (Exception e) {
			e.printStackTrace();
			logger.error("连接通道失败");
			return ExecuteResult.fail("连接通道失败");
		}

		return ExecuteResult.ok();
	}

	public ExecuteResult<?> delete(String id) {
		if (StringUtils.isBlank(id)) {
			return ExecuteResult.fail("id不能为空");
		}
		MerchantChannel entity = repository.findOne(id);
		if (entity == null) {
			return ExecuteResult.fail("商户通道不存在");
		}
		repository.delete(id);
		return ExecuteResult.ok();
	}

	public List<MerchantChannel> findAll() {
		return repository.findAll();
	}
}
